<?php
/**
 * Application class definition
 *   
 * @author Sean Crystal <seancrystal@gmail.com>
 * @package MutantVole
 */
require_once 'interfaces/iApplication.php';
require_once 'components/exceptions/MultiExceptionReporter.php';

/**
 * Initializes the web application, instantiates any necessary objects and
 * hands control off to the requested page
 * @package MutantVole
 * @subpackage Application
 */    
class Application implements iApplication {
	
	/**
     * Constructor
	 * @param array $settings
	 */  	
	public function __construct($settings) {
		$this->settings = $settings;
		
		$this->Init();
	}
	
	/**
 	 * Execute any operations necessary before any Request is processed
	 */ 	
	public function Init() {	
        $this->InitLogger();
	    $this->SetDependencies();
		$this->SetExceptionHandler();
		//$this->SetErrorHandler();
		$this->InitSession();
	}
	
	/**
     * Pass control to the requested Page
	 * @param Page $page
	 * @param Request $request
	 */   	
	public function Go(Page $page, Request $request) {
		// if there is a default renderer defined, pass it into the Page
		$renderer = Injector::Bound('iViewRenderer') ? Injector::GetInstance('iViewRenderer') : null;

		$page->Display($request, $this->session, $renderer);
	}
	
	/**
     * Instantiate the application session store
	 */  	
	protected function InitSession() {
		$this->session = Injector::GetSingleton('iSession');
	}
	
	/**
     * Set a custom error handler to redirect errors as exceptions
     */ 
	protected function SetErrorHandler() {
		// this causes problems with Smarty
		set_error_handler(create_function('$x, $y', 'throw new Exception($y, $x);'), E_ALL & ~E_NOTICE);	
	}
	
	/**
     * Set our custom exception handler
	 */ 	
	protected function SetExceptionHandler() {
		if (Injector::Bound('iExceptionReporter', Injector::SINGLETON)) {
			$exceptionReporter = Injector::GetSingleton('iExceptionReporter');
			
			if ($exceptionReporter instanceof MultiExceptionReporter) {
				$exceptionReporter->AttachReporter(new ScreenExceptionReporter);
				$exceptionReporter->AttachReporter(new LogExceptionReporter(EXCEPTIONS_LOG));
			}
			
			set_exception_handler(array(&$exceptionReporter, 'ReportException'));		
		}
	}
	
	/**
     * Load any dependency bindings defined in the settings
	 */ 	
	protected function SetDependencies() {
		if (count($this->settings['bindings']) > 0) {
			foreach ($this->settings['bindings'] as $binding) {
				Injector::Bind(
					$binding['abstract'], 
					$binding['concrete'], 
					($binding['singleton'] ? Injector::SINGLETON : $binding['namespace']));
			}
		}
	}
	
	protected function InitLogger() {
	    Logger::SetDebug($this->settings['debug']);
	    Logger::SetLogFile(ROOT_DIR ."/{$this->settings['logFile']}");
	}
	
	/**
     * application settings
	 * @var array
	 */  	
	protected $settings;
	
	/**
     * session store instance
	 * @var iSession
	 */  	
	protected $session;
}

?>